#include <random.hpp>
#include <mt19937.h>
#ifdef _WIN32
#include <windows.h>
#endif

SystemRandom::SystemRandom()
{
#ifdef _WIN32
    CryptAcquireContextW((HCRYPTPROV *)&device, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
#else
    device=fopen("/dev/urandom","rb");
#endif
}

SystemRandom::~SystemRandom()
{
#ifdef _WIN32
    CryptReleaseContext((HCRYPTPROV )device, 0);
#else
    fclose((FILE*)device);
#endif
}

unsigned int SystemRandom::next()
{
    unsigned ret;
#ifdef _WIN32
    CryptGenRandom((HCRYPTPROV )device,sizeof(ret),(unsigned char*)&ret);
#else
    fread(&ret,1,4,(FILE*)device);
#endif
    return ret;
}

ClibRandom::ClibRandom(unsigned seed)
{
    srand(seed);
}

ClibRandom::~ClibRandom()
{

}

unsigned int ClibRandom::next()
{
    return rand();
}

Mt19937Random::Mt19937Random(unsigned seed):device(create_mt19937(seed))
{

}

Mt19937Random::~Mt19937Random()
{
    destroy_mt19937((mt19937_engine*)device);
}

unsigned int Mt19937Random::next()
{
    return mt19937_randuint32((mt19937_engine*)device);
}
